#include "..\myLibrary.h"
#include <sys/stat.h>
#include <sys/stat.h>
DWORD WINAPI Download(LPVOID param)
{
    //distribution file
    int part_size = 1024;
    SOCKET Send;
    Send=*(SOCKET *)param;
    SocketG distribution(Send);
    char fileforsend[256];
    recv(Send,fileforsend,sizeof(fileforsend),0);
    struct stat si;
    stat(fileforsend, &si);
    send(Send, (char *)&si.st_size, sizeof(si.st_size), 0);
    int parts_count = si.st_size / part_size;
    int last_part_size = si.st_size % part_size;
    FILE *f = fopen(fileforsend, "rb");
    FileG w(f);
    std::vector <char> buffer(part_size);
    for (int i = 0; i < parts_count; i++)
    {
        fread(&buffer.front(), 1, part_size, f) ;
        send(Send, &buffer.front(), part_size, 0); 
    }
    if (last_part_size)
    {
       fread(&buffer.front(), 1, last_part_size, f);       
       send(Send, &buffer.front(), last_part_size, 0);
    }
    return 0;
}
DWORD WINAPI SharedFile(LPVOID param)
{   
    SOCKET ClientSoc= socket(AF_INET,SOCK_STREAM,0);
    SocketG ServerOnClient(ClientSoc);
    sockaddr_in ForShared;
    ForShared.sin_family=AF_INET;  
    ForShared.sin_port=htons(4444);
    ForShared.sin_addr.S_un.S_addr=INADDR_ANY;
    bind(ClientSoc,(sockaddr*)&ForShared,sizeof(ForShared)); 
    listen(ClientSoc,SOMAXCONN); 
    SOCKET NewDownload;    
    while ((NewDownload = accept(ClientSoc,0,0))!=INVALID_SOCKET)
    {
       DWORD thID;
       HANDLE threadfordownload = CreateThread(NULL, NULL, Download, &NewDownload, NULL, &thID);  
       ThreadG fordownload(threadfordownload);
    }
    closesocket(NewDownload);
    return 0;
}
int main()
{

    Packet Client;
    WSAData WSData;
    WSAStartup(0x202,&WSData);
    WSADataG Ws(WSData);
    SOCKET research=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    sockaddr_in  udp_research;
    int tm = 1;
    setsockopt(research,SOL_SOCKET,SO_BROADCAST,(char*)&tm,sizeof(tm));
    udp_research.sin_family=AF_INET;
    udp_research.sin_port=htons(5555);
    udp_research.sin_addr.s_addr=INADDR_BROADCAST;
    std::string message="yes";
    sendto(research,message.c_str(), message.length() + 1,0,(SOCKADDR *)&udp_research, sizeof(udp_research));

    SOCKADDR_IN nsa;
    std::vector<char> buffer(256);
    int buffer_size = sizeof(buffer)+2;
    int sizeof_nsa = sizeof(nsa);
    recvfrom(research,&buffer.front(), buffer_size,0,(SOCKADDR *)&nsa, &sizeof_nsa);
    buffer.resize(buffer_size);
    std::string addr(buffer.begin(), buffer.end());
    std::cout<<addr;
    char ipserv[256];
    strcpy(ipserv,&addr[0]);
    SOCKET CreateClient = socket(AF_INET,SOCK_STREAM,0);
    SocketG Clients(CreateClient);
    sockaddr_in ForConnect;  
    ForConnect.sin_family=AF_INET;
    ForConnect.sin_port=htons(connected);
    ForConnect.sin_addr.S_un.S_addr=inet_addr(ipserv);
    connect(CreateClient,(sockaddr*)&ForConnect,sizeof(ForConnect)); 
    char buf[128];
    hostent *h;  
    if (gethostname(buf, 128) == 0)
    {
        h=gethostbyname(&buf[0]);
        u_long ip = *(u_long *) h->h_addr_list[0];
        char *cip = inet_ntoa(*(in_addr*)&ip);    
        strcpy(Client.ReturnAddr,cip);           
    } 
    bool onethread=false;
    while(1)
    {   system("cls");
        std::cout<<"Hello"<<"\n"<<"What do you want? \n1.Share file's \n2.Download file's \n3.Show files available\n4.Exit program \nPlease insert you choise: ";
		int _choise = getch ();

		std::cout << char (_choise )<< std::endl;
		if (_choise < 49 || _choise > 52)  
			{
			std::cout<<"Incorrect input\n\n"; 
			system("pause"); continue;
			}
		Client.choise= char (_choise);
//		std::cout << Client.choise << std::endl;
		if( Client.choise=='1')
        {
            std::cout<<"What file you want to share?\nEnter the name: ";       
            std::cin>>Client.NameFile;
            send(CreateClient,(char *)&Client,sizeof(Packet),0);
            if(!onethread)
            {
            //create 1 thread for server
                DWORD thID1;
                HANDLE threadforwait = CreateThread(NULL, NULL, SharedFile, NULL, NULL, &thID1);
                ThreadG forwair(threadforwait);
            }
        }
        else if(Client.choise=='2')
        {
            std::cout<<"What file you want download?\nEnter the name: ";
            std::cin>>Client.NameFile; 
            send(CreateClient,(char *)&Client,sizeof(Packet),0);
            std::vector<char> file(sizeof(Packet)); 
            recv(CreateClient,&file.front(),sizeof(Packet),0);
            Client = *(reinterpret_cast<Packet*>(&file.front()));
            if(Client.choise=='5')
            {
                SOCKET ConnectClient = socket(AF_INET,SOCK_STREAM,0);     
                SocketG Donwload(ConnectClient);
                sockaddr_in ForDownload;  
                ForDownload.sin_family=AF_INET;
                ForDownload.sin_port=htons(shared);
                ForDownload.sin_addr.S_un.S_addr=inet_addr(Client.ReturnAddr);
                connect(ConnectClient,(sockaddr*)&ForDownload,sizeof(ForDownload));
                send(ConnectClient,Client.NameFile,sizeof(Client.NameFile),0);
                int part_size = 1024;
                FILE *f = fopen(Client.NameFile, "wb");
                FileG Write(f);
                long file_size = 0;
                if (recv(ConnectClient, (char *)&file_size, sizeof(file_size), 0) != sizeof(file_size))
                {
                    std::cout<<"recv error\n";
                    system("pause");
                    return -1;
                }
                std::vector <char> buffer(part_size);
                while (file_size)
                {
                    int n = recv(ConnectClient, &buffer.front(), part_size, 0);
                    if (!n)
                    {
                        std::cout<<"disconnected\n";
                        system("pause");
                        return -1;
                    }
                    if (n == SOCKET_ERROR)
                    {
                        std::cout<<"recv error\n";
                        system("pause");
                        return -1;
                    }
                    file_size -= n;
                    if (file_size < 0)
                    {
                        std::cout<<"file_size error\n";
                        system("pause");
                        return -1;
                    }
                    if (fwrite(&buffer.front(), 1, n, f) != n)
                    {
                        std::cout<<"fwrite error\n";
                        system("pause");
                        return -1;
                    }
                }
                fclose(f);
                std::cout<<"complete\n";
				system("pause");
            }
            else
            {
                std::cout<<"This file not found\r\n";
				system("pause");
            }
        }
        else if(Client.choise=='3')
        {
            send(CreateClient,(char *)&Client,sizeof(Packet),0);
            char len;
            std::vector<char> List;
            recv(CreateClient,&len,1,0);
            List.resize(len);
            recv(CreateClient,&List[0],len,0);
            std::cout<<"File for download: \n"<<&List[0];
			system("pause");
        }
        else if(Client.choise=='4')
        {
            send(CreateClient,(char *)&Client,sizeof(Packet),0);
            break;
        }

    }
    return 0;
}